package level.state;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

public class StateHandler
{
	public static State copy(State state)
	{
		State newState = new State();
		StateReader.initiateBlankState(newState, state.getFile());
		Iterator<String> iterator = getIterator(state);
		HashMap<String, StateLayer> newLayers = newState.getLayers();
		while (iterator.hasNext())
		{
			String layerName = (String) iterator.next();
			newLayers.put(layerName, copy(getLayer(state, layerName)));
		}
		calculateMax(newState);
		return newState;
	}

	public static Dimension calculateMax(State state)
	{
		Iterator<String> iterator = getIterator(state);
		Dimension size = new Dimension(0, 0);
		while (iterator.hasNext())
		{
			String layerName = (String) iterator.next();
			int maxX = maxX(getLayer(state, layerName));
			int maxY = maxY(getLayer(state, layerName));
			size.width = (size.width >= maxX ? size.width : maxX);
			size.height = (size.height >= maxY ? size.height : maxY);
		}
		return size;
	}

	public static void addTile(State state, String layerName, Tile tile)
	{
		StateTileLayer layer = (StateTileLayer) getLayer(state, layerName);
		ArrayList<Tile> tiles = layer.getTiles();
		if (tiles.size() != 0) // This block of code checks for tiles on top of
								// one another and deletes the underlying tile
								// in case of stacking.
		{
			int toRemove = -1;
			for (int i = 0; i < tiles.size(); i++)
			{
				if (tiles.get(i).getX() == tile.getX()
						&& tiles.get(i).getY() == tile.getY())
				{
					toRemove = i;
				}
			}
			if (toRemove >= 0)
				tiles.remove(toRemove);
		}
		tiles.add(tile);
	}

	public static void addTile(StateTileLayer layer, Tile tile)
	{
		ArrayList<Tile> tiles = layer.getTiles();
		if (tiles.size() != 0) // This block of code checks for tiles on top of
								// one another and deletes the underlying tile
								// in case of stacking.
		{
			int toRemove = -1;
			for (int i = 0; i < tiles.size(); i++)
			{
				if (tiles.get(i).getX() == tile.getX()
						&& tiles.get(i).getY() == tile.getY())
				{
					toRemove = i;
				}
			}
			if (toRemove >= 0)
				tiles.remove(toRemove);
		}
		tiles.add(tile);
	}

	public static StateLayer getLayer(State state, String layerName)
	{
		return state.getLayers().get(layerName);
	}

	public static StateLayer getLayer(State state, int zOrder)
	{
		StateLayer layer = null;
		Iterator<String> iterator = getIterator(state);
		while (iterator.hasNext())
		{
			StateLayer testLayer = getLayer(state, iterator.next());
			layer = (testLayer.getZOrder() == zOrder ? testLayer : layer);
		}
		return layer;
	}

	public static Iterator<String> getIterator(State state)
	{
		return state.getLayers().keySet().iterator();
	}

	private static StateLayer copy(StateLayer layer)
	{
		if (layer instanceof StateTileLayer)
		{
			return copyTile((StateTileLayer) layer);
		}
		else
			return null;
	}

	private static StateTileLayer copyTile(StateTileLayer layer)
	{
		StateTileLayer newLayer = null;
		newLayer = new StateTileLayer(layer.getName(), layer.getZOrder());
		if (layer.getTiles().size() != 0)
		{
			for (Tile tile : layer.getTiles())
			{
				addTile(newLayer, tile.cloneTile());
			}
		}
		return newLayer;
	}

	private static int maxX(StateLayer stateLayer)
	{
		int max = 0;
		if (stateLayer instanceof StateTileLayer)
		{
			StateTileLayer tileLayer = (StateTileLayer) stateLayer;
			if (tileLayer.getTiles().size() != 0)
			{
				for (Tile tile : tileLayer.getTiles())
				{
					max = (max >= tile.getX() ? max : tile.getX());
				}
			}
		}
		return max;
	}

	private static int maxY(StateLayer stateLayer)
	{
		int max = 0;
		if (stateLayer instanceof StateTileLayer)
		{
			StateTileLayer tileLayer = (StateTileLayer) stateLayer;
			if (tileLayer.getTiles().size() != 0)
			{
				for (Tile tile : tileLayer.getTiles())
				{
					max = (max >= tile.getY() ? max : tile.getY());
				}
			}
		}
		return max;
	}
}
